package encrypt

import (
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"fmt"
	"github.com/forgoer/openssl"
	"io"
	"longmen/server/pkg/common/helper/const"
	string2 "longmen/server/pkg/common/helper/string"
	time2 "longmen/server/pkg/common/helper/timehelper"
	"math/rand"
	"strconv"
	"strings"
	"time"
)

func PwdDesECBEncrypt(account, pwd string) (string, error) {
	if len(account) < 4 {
		return "", errors.New("invalid account size")
	}
	key := []byte(_const.OPENSSL_KEY)
	src := []byte(account[len(account)-4:] + pwd)
	result, err := openssl.DesECBEncrypt(src, key, openssl.PKCS7_PADDING)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(result), nil
}

func TokenWebDesECBEncrypt() (string, error) {
	key := []byte(_const.OPENSSL_KEY)
	src := []byte(time2.LocalTimeToString(time2.TIME_LAYOUT_FORMAT_2) + strconv.Itoa(string2.RandInt(10000, 99999)))
	result, err := openssl.DesECBEncrypt(src, key, openssl.PKCS7_PADDING)
	if err != nil {
		return "", err
	}
	return base64.StdEncoding.EncodeToString(result), nil
}

// md5加密
func Md5(str string) string {
	h := md5.New()
	_, _ = io.WriteString(h, str)
	return fmt.Sprintf("%x", h.Sum(nil))
}

// md5 16
func Md516(str string) string {
	return Md5(str)[8:24]
}

func GenHMAC1(ciphertext, key []byte) []byte {
	mac := hmac.New(sha1.New, key)
	mac.Write([]byte(ciphertext))
	hmac2 := mac.Sum(nil)
	return hmac2
}

func GenHMAC256(ciphertext, key []byte) []byte {
	mac := hmac.New(sha256.New, key)
	mac.Write([]byte(ciphertext))
	hmac2 := mac.Sum(nil)
	return hmac2
}

func randStringBytesMaskImprSrc(n int, letterBytes string) string {
	const (
		letterIdxBits = 6                    // 6 bits to represent a letter index
		letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
		letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
	)
	var src = rand.NewSource(time.Now().UnixNano())
	b := make([]byte, n)
	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
		if remain == 0 {
			cache, remain = src.Int63(), letterIdxMax
		}
		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
			b[i] = letterBytes[idx]
			i--
		}
		cache >>= letterIdxBits
		remain--
	}
	return string(b)
}

func GenHashWithLength(n int) string {
	const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	return randStringBytesMaskImprSrc(n, letterBytes)
}

func Base64urlEncode(data []byte) string {
	str := base64.StdEncoding.EncodeToString(data)
	str = strings.Replace(str, "+", "*", -1)
	str = strings.Replace(str, "/", "-", -1)
	str = strings.Replace(str, "=", "_", -1)
	return str
}

func Base64urlDecode(str string) ([]byte, error) {
	str = strings.Replace(str, "_", "=", -1)
	str = strings.Replace(str, "-", "/", -1)
	str = strings.Replace(str, "*", "+", -1)
	return base64.StdEncoding.DecodeString(str)
}
